package com.wolfsea.launcherdemo
import android.content.Context
import android.graphics.Rect
import android.util.Log
import android.util.SparseArray
import androidx.recyclerview.widget.RecyclerView

/**
 *@desc HorizontalPageLayoutManager2
 *@author liuliheng
 *@time 2023/1/9  10:51
 **/
class HorizontalPageLayoutManager(context: Context, rows: Int, columns: Int) : RecyclerView.LayoutManager(), PageDecorationLastJudge {

    private val mContext = context
    private val mRows = rows
    private val mColumns = columns

    private val onePageSize = rows * columns

    private var pageSize = 0
    private var scrollTotalWidth = 0
    private var offsetX = 0

    private val allItemsRect by lazy {
        SparseArray<Rect?>()
    }

    override fun onAttachedToWindow(view: RecyclerView?) {
        super.onAttachedToWindow(view)
    }

    override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams =
        RecyclerView.LayoutParams(
            RecyclerView.LayoutParams.WRAP_CONTENT,
            RecyclerView.LayoutParams.WRAP_CONTENT
        )

    override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State?) {
        super.onLayoutChildren(recycler, state)
        if (itemCount == 0) {
            removeAndRecycleAllViews(recycler!!)
            return
        }
        if (state?.isPreLayout!!) {
            return
        }
        //计算总页数
        computePageSize(state)
        Log.d(TAG, "pageSize:${pageSize}")
        //可以滚动的最大值
        scrollTotalWidth = (pageSize - 1) * width
        //分离view
        detachAndScrapAttachedViews(recycler!!)

        var totalItemWidth = 0
        var totalItemHeight = 0
        var totalPageWidth = 0
        for (i in 0.until(itemCount)) {
            val view = recycler.getViewForPosition(i)
            addView(view)
            measureChildWithMargins(view, 0, 0)
            val viewWidth = getDecoratedMeasuredWidth(view) - paddingStart - paddingEnd
            val viewHeight = getDecoratedMeasuredHeight(view) - paddingTop - paddingBottom
            val itemSpace = ((width - mColumns * viewWidth).toFloat() / (mColumns + 1)).toInt()
            val itemTop = mContext.resources.getDimension(R.dimen.dp_20).toInt()
            var rect = allItemsRect[i]
            if (rect == null) {
                rect = Rect()
            }
            val left = itemSpace + totalItemWidth + totalPageWidth
            val top = itemTop + totalItemHeight
            val right = left + viewWidth
            val bottom = top + viewHeight
            rect.set(
                left,
                top,
                right,
                bottom
            )
            allItemsRect[i] = rect

            totalItemWidth += itemSpace + viewWidth
            if ((i + 1) % mColumns == 0) {
                totalItemWidth = 0
                totalItemHeight += itemTop + viewHeight
            }

            if ((i + 1) % onePageSize == 0) {
                totalPageWidth += width
                Log.d(TAG, "(i + 1):${(i + 1)},totalPageWidth:${totalPageWidth}")
                totalItemHeight = 0
            }

            //每添加完一个 回收一个
            removeAndRecycleView(view, recycler)
        }

        //回收 添加itemView
        recycleAndFillItems(recycler, state)
    }

    //水平滚动
    override fun canScrollHorizontally(): Boolean = true

    //滚动范围
    override fun computeHorizontalScrollRange(state: RecyclerView.State): Int {
        computePageSize(state)
        return pageSize * width
    }

    //滚动偏移量
    override fun computeHorizontalScrollOffset(state: RecyclerView.State): Int = offsetX

    //滚动扩展
    override fun computeHorizontalScrollExtent(state: RecyclerView.State): Int = width

    //水平滚动  相对滚动
    override fun scrollHorizontallyBy(
        dx: Int,
        recycler: RecyclerView.Recycler?,
        state: RecyclerView.State?
    ): Int {
        //分离view
        detachAndScrapAttachedViews(recycler!!)
        //计算偏移量
        val newX = offsetX + dx
        val result = if (newX > scrollTotalWidth) {
           scrollTotalWidth - offsetX
        } else if (newX < 0){
            -offsetX
        } else {
            dx
        }
        offsetX += result
        //偏移
        offsetChildrenHorizontal(-result)
        //回收添加item
        recycleAndFillItems(recycler, state)
        return result
    }

    override fun onDetachedFromWindow(view: RecyclerView?, recycler: RecyclerView.Recycler?) {
        super.onDetachedFromWindow(view, recycler)
        offsetX = 0
    }

    override fun isLastRow(position: Int): Boolean {
        if (position in 0 until itemCount) {
            var indexOfPage = position % onePageSize
            indexOfPage++
            return indexOfPage > (mRows - 1) * mColumns && indexOfPage <= onePageSize
        }
        return false
    }

    override fun isLastColumn(position: Int): Boolean {
        if (position in 0 until itemCount) {
            var newValue = position
            newValue++
            return newValue % mColumns == 0
        }
        return false
    }

    override fun isPageLast(position: Int): Boolean {
        var newValue = position
        newValue++
        return newValue % onePageSize == 0
    }

    private fun recycleAndFillItems(recycler: RecyclerView.Recycler?, state: RecyclerView.State?) {
        if (state?.isPreLayout!!) {
            return
        }

        val displayRect = Rect(
            paddingStart + offsetX,
            paddingTop,
            width - paddingStart - paddingEnd + offsetX,
            height - paddingTop - paddingBottom
        )

        val childRect = Rect()
        for (i in 0.until(childCount)) {
            val child = getChildAt(i)
            if (child != null) {
                childRect.set(
                    getDecoratedLeft(child),
                    getDecoratedTop(child),
                    getDecoratedRight(child),
                    getDecoratedBottom(child)
                )
                if (!Rect.intersects(displayRect, childRect)) {
                    removeAndRecycleView(child, recycler!!)
                }
            }
        }

        for (i in 0.until(itemCount)) {
            val rect = allItemsRect[i]
            if (Rect.intersects(displayRect, rect!!)) {
                val view = recycler?.getViewForPosition(i)
                addView(view)
                measureChildWithMargins(view!!, 0, 0)
                layoutDecorated(
                    view,
                    rect.left - offsetX,
                    rect.top,
                    rect.right - offsetX,
                    rect.bottom,
                )
            }
        }
    }

    private fun computePageSize(state: RecyclerView.State?) {
        val itemCount = state?.itemCount ?: 0
        pageSize = itemCount / onePageSize + if (itemCount % onePageSize == 0) 0 else 1
    }

    fun getPageSize(): Int = itemCount / onePageSize + if (itemCount % onePageSize == 0) 0 else 1

    companion object {
        const val TAG = "HorizontalPageLayoutManager2"
    }

}